// 日滚动撮合
import { yunNao } from "@src/api/yunNao"
import { getPrivateCommonParams } from "@src/spotMarketPrivateData/data"
import { requestSDspotMarketZcq } from "@src/api/fetch"
import { throttle } from 'lodash'
import dayjs from "dayjs"
import { DayRollBDDataItem, MyDeclarationInfoRes } from "./type"
import { AsyncRecursion, CbParams, creatAsyncRecursion } from '@src/utils/asyncRecursion'
import { promisetTimeOut } from "@src/utils/common"

/** 记录timer */
const allTimeOutTimerList: Array<ReturnType<typeof setTimeout>> = []
/** 清除所有 timeOut */
const clearAllTimeOut = () => {
  allTimeOutTimerList.forEach(val => clearTimeout(val))
  allTimeOutTimerList.length = 0
}

/** 在交易时段时 每一轮供需数据的间隔时间 */
const SPingTimerTime = 1000
/** 非交易时段时 每一轮供需数据的间隔时间 */
const SPTimerTime = 10000
/** 记录供需timer */
const allSPTimeOutTimerList: Array<ReturnType<typeof setTimeout>> = []
/** 清除所有供需 timeOut */
const clearAllSPTimeOut = () => {
  allSPTimeOutTimerList.forEach(val => clearTimeout(val))
  allSPTimeOutTimerList.length = 0
}

/** 获取申报日期为当天 的开盘信息 */
export const getTodayParamsInfo = async ({ headers, certainDate }: { headers: HeadersInit, certainDate?: string }) => {
  try {
    const todayDate = certainDate || dayjs().format('YYYY-MM-DD')
    const data = await requestSDspotMarketZcq(
      `https://pmos.sd.sgcc.com.cn:18080/zcq/lxchjy/lxchjy.do?method=getKpxx&jylx=0&jyxz=all&sdate=${todayDate}&edate=${todayDate}&_=${new Date().getTime()}`,
      undefined,
      { method: 'GET', headers }
    )
    return Promise.resolve(data?.data?.[0])
  } catch (e) {
    console.error(e)
  }
}

/** 获取单个交易代码 单天的数据 */
const getOneRollData = async ({ headers, paramsInfo }: { headers: HeadersInit, paramsInfo: Record<any, any> }) => {
  try {
    const formParams = new URLSearchParams(paramsInfo)

    const dataObj = await requestSDspotMarketZcq(
      `https://pmos.sd.sgcc.com.cn:18080/zcq/lxchjy/lxchjy.do?method=getJyjgInfo`,
      formParams,
      { method: 'POST', headers }
    )
    console.log('getOneRollData')
    let data: DayRollBDDataItem[] = dataObj?.data || []
    if (data.length) {
      // data = data.map((item:Record<any,any>) => {
      //   const newObj:Record<any,any> = {}
      //   Object.keys(item).forEach((key:string) => {
      //     newObj[key] = item[key] === '-' ? '' : item[key]
      //   })
      //   return newObj
      // })
      data = JSON.parse(JSON.stringify(data).replace(/\"-\"/g, '\"\"'))
    }
    return Promise.resolve(data)
  } catch (e) {
    console.error(e)
  }
}

/** 判断当前时间是否能获取滚动撮合数据 */
const isGetRollData = () => {
  const nowNum = Number(dayjs().format('HHmm'))
  const getDataStartEnd = [1328, 1432]
  // const getDataStartEnd = [1030, 2359]
  console.log('getDataStartEnd', String(getDataStartEnd))
  return nowNum > getDataStartEnd[0] && nowNum < getDataStartEnd[1]
}

/** 交易代码列表 */
let supplyDemandJYDMlist: string[] = []
/** 设置交易代码列表 */
const setSupplyDemandJYDMlist = (dataList: DayRollBDDataItem[]) => {
  if ([24, 48].includes(supplyDemandJYDMlist.length)) return

  supplyDemandJYDMlist = []
  dataList.forEach(item => item.JYDM && supplyDemandJYDMlist.push(item.JYDM))
}

/** 获取滚动撮合数据 */
let paramsInfo: undefined | Record<any, any>
const getRollData = async ({ headers, unitid }: { headers: HeadersInit, unitid: string }) => {
  console.log('getRollData', dayjs().format('YYYY-MM-DD HH:mm:ss'))
  try {
    if (!isGetRollData()) {
      paramsInfo = undefined
      supplyDemandJYDMlist = []
      return Promise.resolve()
    }
    if (!paramsInfo) {
      paramsInfo = await getTodayParamsInfo({ headers })
    }
    if (!paramsInfo) {
      console.error('getTodayParamsInfo 失败')
      return Promise.resolve()
    }
    const { KPID, PDATE } = paramsInfo
    if (!KPID) {
      console.error('getTodayParamsInfo KPID 失败')
      return Promise.resolve()
    }

    const bdtime2 = 'D' + dayjs(PDATE).add(2, 'day').format('YYYYMMDD')
    const bdtime3 = 'D' + dayjs(PDATE).add(3, 'day').format('YYYYMMDD')
    const params = {
      kpId: KPID,
      jyjd: 2
    }
    const d2Data = await getOneRollData({ headers, paramsInfo: { ...params, bdtime: bdtime2 } })
    const d3Data = await getOneRollData({ headers, paramsInfo: { ...params, bdtime: bdtime3 } })

    // 保存交易代码
    setSupplyDemandJYDMlist([...(d2Data || []), ...(d3Data || [])])

    const dayRollData = [
      {
        declareDate: PDATE, // 申报日期
        bdtime: bdtime2, // 标的日期 D+2
        data: d2Data
      },
      {
        declareDate: PDATE,
        bdtime: bdtime3, // 标的日期 D+3
        data: d3Data
      }
    ]

    const saveDataList = {
      ...getPrivateCommonParams({ thirdId: unitid }),
      itemCode: 'medium_day_roll_trade',
      dayRollData
    }

    console.log('存储数据：getRollData', saveDataList)
    await yunNao.saveJson(saveDataList)
    console.log("获取数据存储成功 getRollData", dayjs().format("YYYY-MM-DD HH:mm:ss"))
  }catch(e) {
    console.error(e)
  }
}

/** 记录申报timer */
const allDeclareTimerList:Array<ReturnType<typeof setTimeout>> = []
/** 清除所有申报 timeOut */
const clearDeclareTimeOut = () => {
  allDeclareTimerList.forEach(val => clearTimeout(val))
  allDeclareTimerList.length = 0
}
let paramsInfoDeclaration: undefined | Record<any, any>
/** 日滚动撮合交易 获取我的申报信息-申报明细 */
export const declarationDetailsList = async ({ headers, unitid, isAuto = true}: { headers: HeadersInit, unitid: string, isAuto?:Boolean }) => {
  try {
    if (!isGetRollData() && isAuto) {
      paramsInfoDeclaration = undefined
      return true
    }
    if(isAuto) {
      clearDeclareTimeOut()
    }
    if(!paramsInfoDeclaration) paramsInfoDeclaration = await getTodayParamsInfo({ headers })
    const { KPID } = paramsInfoDeclaration || {}
    if (!KPID) {
      console.error('getTodayParamsInfo KPID 失败')
      return true
    }
    const tradeDate = dayjs().format('YYYY-MM-DD HH:mm:ss')
    const sendParams = new URLSearchParams({
      draw: 1, // 请求次数
      start: 0, // 起始索引
      length: 999, // 每页显示条数 给个极大值
      kpid: KPID || '',
    } as any)

    let saveDataList = await requestSDspotMarketZcq(
      `https://pmos.sd.sgcc.com.cn:18080/zcq/lxchjy/lxchjy.do?method=dataLsjl`,
      sendParams,
      { method: 'POST', headers }
    )
    saveDataList = (saveDataList?.data || []).map((item:MyDeclarationInfoRes)=>{
      return {
        ...item,
        tradeDate
      }
    })
    console.log('爬取数据成功-我的申报信息：declarationDetailsList', saveDataList)
    const saveObj = {
      ...getPrivateCommonParams({ thirdId: unitid }),
      tradeDate: tradeDate,
      itemCode:'save_declare_detail',
      data:saveDataList || []
    }
    console.log('存储的数据-我的申报信息：declarationDetailsList',saveObj)
    await yunNao.saveJson(saveObj)
    console.log("爬取数据存储成功-我的申报信息：declarationDetailsList", dayjs().format("YYYY-MM-DD HH:mm:ss"))
  } catch (e) {
    console.error('爬取数据失败-我的申报信息：declarationDetailsList', e)
  } finally {
    if(isAuto) {
      clearDeclareTimeOut()
      const allDeclareTimer = setTimeout(() => declarationDetailsList({headers, unitid, isAuto:true}), 30*1000)
      allDeclareTimerList.push(allDeclareTimer)
    }
  }
}

/** 日滚动撮合交易 获取我的申报信息-申报明细 */
export const getDayRollDeclarationDetailsListThrottle = throttle(declarationDetailsList, 2000, { trailing: true, leading: false })

type OneDMSupplyDemandParams = {
  headers: HeadersInit,
  params: {
    kpid: string,
    jydm: string, // 交易代码
    declareDate: string // 申报日期
  }
}
/** 获取一个交易代码的供需数据 */
const getOneDMSupplyDemandData = async ({ headers, params }: OneDMSupplyDemandParams) => {
  try {
    const formParams = new URLSearchParams(params)

    const dataObj = await requestSDspotMarketZcq(
      `https://pmos.sd.sgcc.com.cn:18080/zcq/lxchjy/lxchjy.do?method=getGpxx`,
      formParams,
      { method: 'POST', headers }
    )
    console.log('getOneDMSupplyDemandData')
    return Promise.resolve({ ...params, data: dataObj?.data || [] })
  } catch (e) {
    console.error(e)
  }
}

/** 获取所有交易代码的供需数据 */
const getAllDMSupplyDemandData = async ({ headers, unitid }: { headers: HeadersInit, unitid: string }) => {
  console.log('getAllDMSupplyDemandData', dayjs().format('YYYY-MM-DD HH:mm:ss'))
  let SPTimeReal = SPingTimerTime
  try {
    clearAllSPTimeOut()
    if (!isGetRollData()) {
      SPTimeReal = SPTimerTime
      return Promise.resolve()
    }

    SPTimeReal = SPingTimerTime

    if (!supplyDemandJYDMlist.length) {
      console.error('getAllDMSupplyDemandData 无交易代码列表')
      return Promise.resolve()
    }
    if (!paramsInfo) {
      console.error('getTodayParamsInfo 失败')
      return Promise.resolve()
    }
    const { KPID, PDATE } = paramsInfo
    if (!KPID) {
      console.error('getTodayParamsInfo KPID 失败')
      return Promise.resolve()
    }

    const reqParamsList: OneDMSupplyDemandParams[] = supplyDemandJYDMlist.map(jydm => ({ headers, params: { kpid: KPID, jydm, declareDate: PDATE } }))

    const allNodeData: CbParams = await creatAsyncRecursion(AsyncRecursion, {
      stepAsyncFnParamsList: reqParamsList,
      stepAsyncFn: getOneDMSupplyDemandData,
      stepCb: async () => await promisetTimeOut(100),
      stepAsyncNum: 1,
      errBreak: false
    }).start()

    const saveDataList = {
      ...getPrivateCommonParams({ thirdId: unitid }),
      itemCode: 'medium_day_roll_supply_demand',
      dayRollSupplyDemand: (allNodeData?.allResultList || []).flat()
    }

    console.log('存储数据：getAllDMSupplyDemandData', saveDataList)
    await yunNao.saveJson(saveDataList)
    console.log("获取数据存储成功 getAllDMSupplyDemandData", dayjs().format("YYYY-MM-DD HH:mm:ss"))
  }catch(e) {
    console.error(e)
  } finally {
    clearAllSPTimeOut()
    const SPtimer = setTimeout(() => getAllDMSupplyDemandData({ headers, unitid }), SPTimeReal)
    allSPTimeOutTimerList.push(SPtimer)
  }
}

/** 获取所有交易代码的供需数据 节流*/
const getAllDMSupplyDemandDataThrottle = throttle(getAllDMSupplyDemandData, 2000, { trailing: true, leading: false })

/** 手动 获取滚动撮合数据 */
export const getRollDataHandle = async ({ headers, unitid, certainDate }: { headers: HeadersInit, unitid: string, certainDate: string }) => {
  console.log('getRollDataHandle', dayjs().format('YYYY-MM-DD HH:mm:ss'))
  try {
    const paramsInfoHandle = await getTodayParamsInfo({ headers, certainDate })

    if (!paramsInfoHandle) {
      console.error('getTodayParamsInfo 失败')
      return Promise.resolve()
    }
    const { KPID, PDATE } = paramsInfoHandle
    if (!KPID) {
      console.error('getTodayParamsInfo KPID 失败')
      return Promise.resolve()
    }

    const bdtime2 = 'D' + dayjs(PDATE).add(2, 'day').format('YYYYMMDD')
    const bdtime3 = 'D' + dayjs(PDATE).add(3, 'day').format('YYYYMMDD')
    const params = {
      kpId: KPID,
      jyjd: 2
    }
    const d2Data = await getOneRollData({ headers, paramsInfo: { ...params, bdtime: bdtime2 } })
    const d3Data = await getOneRollData({ headers, paramsInfo: { ...params, bdtime: bdtime3 } })

    const dayRollData = [
      {
        declareDate: PDATE, // 申报日期
        bdtime: bdtime2, // 标的日期 D+2
        data: d2Data
      },
      {
        declareDate: PDATE,
        bdtime: bdtime3, // 标的日期 D+3
        data: d3Data
      }
    ]

    const saveDataList = {
      ...getPrivateCommonParams({ thirdId: unitid }),
      itemCode: 'medium_day_roll_trade',
      dayRollData
    }

    console.log('存储数据：getSaveAllDayTradeInfo', saveDataList)
    await yunNao.saveJson(saveDataList)
    console.log("获取数据存储成功", dayjs().format("YYYY-MM-DD HH:mm:ss"))
  }catch(e) {
    console.error(e)
  }
}

const intervalSeconds = 30
/** 创建所有类型对应的所有的请求 的  请求间隔*/
const createAllIntervalReq = ({ headers, unitid }: { headers: HeadersInit, unitid: string }) => {
  console.log(
    `%c 创建滚动撮合getRollData，每${intervalSeconds}秒执行一次`,
    'background:#35495e ; padding: 1px; border-radius: 3px 0 0 3px;  color: #fff',
  )

  clearAllTimeOut()

  const timeOutTimer = setTimeout(() => {
    getRollData({ headers, unitid })
    createAllIntervalReq({ headers, unitid })
  }, intervalSeconds * 1000)

  // getRollData({headers, unitid})

  allTimeOutTimerList.push(timeOutTimer)
}


/** 创建所有类型的所有接口的定时请求 */
const createGetRollDataLoop = ({ headers, unitid }: { headers: HeadersInit, unitid: string }) => {
  paramsInfo = undefined
  paramsInfoDeclaration = undefined
  supplyDemandJYDMlist = []
  console.log('执行 createGetRollDataLoop =======++++')

  getRollData({ headers, unitid })
  createAllIntervalReq({ headers, unitid })

  clearAllSPTimeOut()
  getAllDMSupplyDemandDataThrottle({ headers, unitid })
}

/** 唯一出口函数 */
export const createGetRollDataLoopThrottle = throttle(createGetRollDataLoop, 5000, { trailing: true, leading: false })
